# coding=utf-8
# INF 8007 lab 2 - Mikael Guillemot et Thibaut Stimpfling 


import os
import urllib
import re

class analyse():
    
    dico = None
    
    def process (self,texte):
        # Initialisation de paramètres
        espaceur = "</BR>\n"
        mots = 0 
        syllabes = 0
        resultat=[]
        # Gestion de exceptions 
        liste = texte.split(".")
        nphrases = len(liste)-1
        try :
            # Pour chacune des phrases contenue dans la liste
            for line in liste :
                liste_mots = self.split_list_mots(line)                 # Découpage d'une phrase en une liste contenant les mots de celle-ci
                result = self.lookup_list_in_dic(liste_mots)            # 1 ème phase de recherche dans le dictionnaire pour chacun des mots contenus
    
                mots += result[1][0]                                    # Récuppération du nombre de mots de la recherche 
                syllabes += result[1][1]                                # Récuppération du nombre de syllabe de la recherche
                result = self.last_lookup(result[0])                    # 2 nd lookup sur les mots 
                mots += result[1][0]                                    # Nombre de mots supplémentaires comptés ERREEEUUUUUURRR
                syllabes += result[1][1]                                # Ajout du nombre de syllabe calculés par la 2nde recherche
                if result[0] !=[]:                                      # Si au moins un mot n'est pas présent dans le dictionnaire alors 
                    resultat.append(result[0])                          # ajout à la liste de retour des mots non traités
        except :
            print "Erreur dans le traitement des données"               # En cas d'erreur 
        #Calcul de l'indice de Lisibilité
        
        result_char = " Mot(s) non traité(s) : "+espaceur
        if ((mots !=0) and (nphrases == 0) ):
            nphrases = 1   
        if resultat != [] :
            for liste_mots_non_traites in resultat :
                for mots_non_traites in liste_mots_non_traites :
                    result_char += "  "+str(mots_non_traites)
        else :
            result_char +=" aucun mot ignoré"+espaceur
        result_char =result_char+espaceur+espaceur+"nombre de phrase : "+str(nphrases) +espaceur +"nombre de mots : "+ str(mots) +espaceur +"nombre de syllabes : "+str(syllabes) +espaceur
            # ATTENTION ici c'est un fragment de code html qui est dans la chaine, l'affichage est a retirer apres debug (ou a revoir)
        try :    
            fre = 206.835 - 1.015 * mots / nphrases - 84.6 * syllabes / mots
            result_char =result_char +"FRE : "+str(fre)
            #  Affichag du resultat et des variables du calcul
        except ZeroDivisionError:
            result_char +=" Indice de lisibilité non valide : Nombre de phrases nul "
        return result_char
    
    
    # 2nde fonction de recherche dans un dictionnaire 
    # Paramètres d'entrées : # liste dont les éléments sont les mots à analyser
    #                         # dictionnaire de référence
    
    # Test à réaliser : envoie un mot pas dans un dic un mot dans le dic et fornat de sortie
    def last_lookup(self,liste):
                                                                                    # Initialisation
        fail_list = []
        syllabes =0
        mots =0
                                                                                    # Gestion des erreurs lors de la recherche dans le dictionnaire
    
                                                                                    # Pour chacun des mots de la liste 
        for mot_compose in liste:
            mot_compose = mot_compose.replace("'", " ").replace("-", " ").split(" ")# on remplace les ' et - par des espaces et l'on crée une nouvelle liste ERRRREUR 
                                                                                    # Pour chacun des mots contenus dans la liste découpée
            for mot  in mot_compose :
                if (mot == "") :                                                    # On ignore le caractère vide
                    continue
                else : 
                    try :                                                           # Sinon 
                        syllabes += eval(self.dico[mot])                            # Récupération du nombre de syllabe(s) associées
                        mots += 1                                                   # Additionne le nombre de mots
                    except KeyError :                                               # Erreur traitée : mots non présent dans le dico
                        fail_list.append(mot)                                       # Ajout du mot non traité à la liste de retour
        result_liste =((fail_list),(mots,syllabes))                                 # Création de la liste de retour
        return result_liste    
    
    
    
    
                                                                
    
    # Fonction de découpage d'une liste (séparation des mots)
    # Paramètre d'entrée : liste à découper
    # Paramètre de retour : liste mise en forme et découpée     
    

    def split_list_mots(self,liste):
        # Mise en forme (minuscule, retire les caractères '"', ',' et '\t' ' ' espace, : )
        liste = liste.lower()
        # Découpage de la liste pour séparer les mots contenus entre deux espaces
        liste_mots = re.split("[() \\\,:\n\t\]\[|\}{\*!><,\r\"]*", liste,re.UNICODE)
        return liste_mots
    
    
    
    
    
    
        
    # Fonction de création d'un dictionnaire 
    # Paramètres d'entrées : # lexique
    #                         # Nombre de lignes présentes au début du texte à ignorer
    #                         # Position dans le lexique du mot servant de clé au dictionnaire
    #                         # Position dans le lexique du nombre de syllabe servant de résultat dans le dico
           


    def create_dictionary(self,file_in,ind1,ind2,ind3):
        liste = file_in.split("\n")
        # Suppression des "ind1" premières colones inutiles (données de type descriptive)
        del liste[:ind1]
        
        # création du dictionnaire
        
        # Mise en forme des données brutes
        l=[]
        for i in liste:                                                     # Pour chacune des lignes 
            i = i.split("\t")                                               # Création d'une liste contenant les différentes info pour chaque mot
            if (len(i) < ind3) :                                            # Vérification en cas d'irrégularité du lexique
                continue
            else :                                                          # Création d'une liste contenant le mots et le nombre de syllabes associées
                l.append((i[ind2], i[ind3]))                                # position 0 et 23 pour nous
        self.dico = dict(l)                                                 # Création du dictionnaire
        
        
        
        
        
    
    # Fonction utilisée pour les mots dont l'entrée n'existe pas dans le dictionnaire
    # Vise à combiner deux mots et voir si ce dernier existe dans le dernier (cas "a jeun", "a l'instar" ...)
    # Paramètres d'entrée : Liste de mots à combiner
    #                        Dictionnaire
    # Paramètre de sortie : liste des mots non trouvés, mots comptés, syllabes trouvées

    def two_words_in_one_lookup (self,liste):
        # Initialisation
        fail_list = []
        mots = 0
        syllabes = 0
                                                                                    # Si le mot "Combo" est dans le dictionnaire alors 
        if ((liste[0] + " " + liste[1]) in self.dico) :
            new_mot = liste[0] + " " + liste[1]
            syllabes = eval(self.dico[new_mot])                                     # Calcul du nombre de syllabes correspondantes
            mots = len(new_mot.replace("'", " ").split(" "))                        # Calcul du nombre de mots contenus dans ce mot combo
    
        else :                                                                        
            fail_list.append(liste[0])                                              # Sinon on ajoute les deux mots à la liste des mots 
            fail_list.append(liste[1])                                              # non traités  
        return_list = [(fail_list), (mots, syllabes)]                               # Création de la liste de retour
        return return_list
    
    
    
    
    
    
    
    
    # Fonction de recherche de chacun des mots contenus dans un dictionnaire
    # Paramètres d'entrée : # Liste dont les éléments sont les mots à analyser
    #                        # Dicionnaire 
    # Paramètre de retour : # Liste contenant les mots non trouvés, et pour les recherche valide, le nombre de syllabes et mots trouvés    
    #Test un mot non dictionnaire, un mot double et un mot dans le dic et comparaison par rapport à valeur attendu
    
    def lookup_list_in_dic (self,liste):
        # Initialisation
        syllabes = 0
        fail_list = []
        mots = 0
        tampon =['']*2                                   # Variable tampon pour contenir deux mots à analyser de manière conjointe
        for mot in liste:                                # Pour chacun des mots contenus dans la liste
            if mot == "":                                # On ignore le caractère vide 
                continue
            elif mot in self.dico :                      # si le mot est dans le dictionnaire
                syllabes_tmp = eval(self.dico[mot])      # Calcul du nombre de syllabes
                syllabes +=syllabes_tmp
                temp = mot.replace("'", " ").split(" ")  # Calcul du nombre de mot à contenus dans le mot analysé
                mots_tmp = len(temp)                     # Additionne au nombre actuel de mots
                mots += mots_tmp
                tampon[0]= mot                           # Mise en mémoire du dernier mot matché
    
            else :
    
                tampon[1]=mot                                    # Mise en mémoire du mot non matché
                result =self.two_words_in_one_lookup(tampon)     # Tentative de combiner les deux mots 
                if result[1][0] != 0:                            # Si match alors 
                    mots -=mots_tmp                              # décompte du dernier mot matché déjà compté
                    syllabes -=syllabes_tmp                      # décompte du nombre de syllabes déjà comptés
                    mots += result[1][0]                         # Ajout du nombre de syllabes / mots trouvées
                    syllabes += result[1][1]        
                else :
                    fail_list.append(tampon[1])
                tampon[0]=mot                                    # Mise à jour des valeurs
                mots_tmp = 0
                syllabes_tmp = 0
        return_list = [(fail_list), (mots, syllabes)]            # Création de la liste de retour
        return return_list
    
    def dictionnaire_init (self):
        #on verifi la presence du dico dans le repertoir de travail. 
        #Si on ne le trouve pas un essai de le recuperer sur le web
        localdic="./Lexique372.txt"
        if os.path.isfile(localdic):
            print "travail a partir de la version local du dictionnaire"
            file_in =open(localdic)
        else :
            try : 
                urldic= "http://www.cours.polymtl.ca/inf8007/Tp/20121/Lexique372.txt"
                print "recuperation de la version distante du dictionnaire..."
                print urldic
                file_in = urllib.urlopen(urldic)
            except :
                print "erreur lors de la tentative de recuperation du dictionnaire !"
                return False
            
        file_in = file_in.read().decode('latin1 ').encode ('utf8 ')
        
        self.create_dictionary( file_in,0,0,23)
        return True
